package com.cn.tous.auth.filer;

import com.cn.tous.auth.security.PasswordAuthenticationConverter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * @author mengwei
 * @description PasswordOAuth2TokenEndpointFilter
 * @createDate 2025/7/30 9:49
 */

public class PasswordOAuth2TokenEndpointFilter extends OncePerRequestFilter {

    private static final String DEFAULT_TOKEN_ENDPOINT_URI = "/oauth2/token";


    private ProviderManager providerManager;

    private PasswordAuthenticationConverter passwordAuthenticationConverter;


    public PasswordOAuth2TokenEndpointFilter(ProviderManager providerManager
            , PasswordAuthenticationConverter passwordAuthenticationConverter) {
        this.providerManager = providerManager;
        this.passwordAuthenticationConverter = passwordAuthenticationConverter;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        if (!DEFAULT_TOKEN_ENDPOINT_URI.equals(request.getServletPath())) {
            filterChain.doFilter(request, response);
            return;
        }
        Authentication authentication = passwordAuthenticationConverter.convert(request);

        Authentication authenticate = providerManager.authenticate(authentication);
        if (authenticate != null) {
            SecurityContextHolder.getContext().setAuthentication(authenticate);
        } else {
            throw new OAuth2AuthenticationException(new OAuth2Error("账号密码认证失败", "账号密码认证失败", null));
        }
        providerManager.authenticate(authenticate);
        filterChain.doFilter(request, response);
    }
}
